<?php

namespace App\Library\Service;

use App\Library\Logic\AddressLogic;
use App\Library\Logic\OperateLogLogic;
use App\Library\Logic\ShopImageLogic;
use App\Library\Logic\ShopOrderExtLogic;
use App\Library\Logic\ShopOrderGoodsLogic;
use App\Library\Logic\ShopOrderLogic;
use App\Library\Logic\ShopOrderReturnLogic;
use App\Library\Logic\ShopUserAddressLogic;
use App\Library\Requests\Base\SerialNumberRequest;
use App\Library\Requests\ProductOrderReturn\AgreeRefundProductRequest;
use App\Library\Requests\ProductOrderReturn\ProductOrderReturnAddExpressRequest;
use App\Library\Requests\ProductOrderReturn\ProductOrderReturnApplyRequest;
use App\Library\Requests\ProductOrderReturn\ProductOrderReturnAuditRequest;
use App\Library\Requests\ProductOrderReturn\ProductOrderReturnPageRequest;
use App\Library\Requests\ProductOrderReturn\ProductOrderReturnSellerPageRequest;
use App\Library\Requests\ProductOrderReturn\ProductOrderReturnUserPageRequest;
use App\Library\Service\Payment\WechatService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;

class ProductOrderReturnService extends BaseService
{
    /**
     * @param ShopOrderReturnLogic $logic
     */
    public function __construct(ShopOrderReturnLogic $logic)
    {
        $this->logic = $logic;
    }

    /**
     * userPaging
     * @param ProductOrderReturnPageRequest $request
     * @return JsonResponse
     */
    public function paging(ProductOrderReturnPageRequest $request): JsonResponse
    {
        return success($this->logic->paging($request));
    }

    /**
     * userPaging
     * @param ProductOrderReturnUserPageRequest $request
     * @return JsonResponse
     */
    public function userPaging(ProductOrderReturnUserPageRequest $request): JsonResponse
    {
        return success($this->logic->userPaging($request));
    }

    /**
     * sellerPaging
     * @param ProductOrderReturnSellerPageRequest $request
     * @return JsonResponse
     */
    public function sellerPaging(ProductOrderReturnSellerPageRequest $request): JsonResponse
    {
        return success($this->logic->sellerPaging($request));
    }

    /**
     * detail
     * @param SerialNumberRequest $request
     * @return JsonResponse
     */
    public function detail(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->detail($request->serialNumber);
        if (is_null($model)) return fail(433);
        $this->hDetail($model);
        return success($model);
    }

    /**
     * userDetail
     * @param SerialNumberRequest $request
     * @return JsonResponse
     */
    public function userDetail(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->userDetail($request->serialNumber);
        if (is_null($model)) return fail(433);
        $this->hDetail($model);
        $model->express_no = is_null($model->oneLogistics) ? '' : $model->oneLogistics->express_no;
        return success($model);
    }

    /**
     * sellerDetail
     * @param SerialNumberRequest $request
     * @return JsonResponse
     */
    public function sellerDetail(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->sellerDetail($request->serialNumber);
        if (is_null($model)) return fail(433);
        $this->hDetail($model);
        $model->refundAddress;
        $model->express_no = is_null($model->oneLogistics) ? '' : $model->oneLogistics->express_no;
        return success($model);
    }

    /**
     * apply
     * @param ProductOrderReturnApplyRequest $request
     * @return JsonResponse
     */
    public function apply(ProductOrderReturnApplyRequest $request): JsonResponse
    {
        $order = ShopOrderLogic::findBySerialNumber($request);
        if (is_null($order) || $order->buy_user_id !== USERID) return fail(433);
        else if ($order->order_status === 2) return failMessage('订单还未支付');
        else if (in_array($order->ext->status_after_sale, [1, 2])) return failMessage('有未处理完的售后');
        else if (!is_null($order->ext->refund_cut_off_at)) return failMessage('订单已经完结');
        else if ($order->plug > 0 && $order->ext->user_id === config('app.plugId')) return failMessage('平台扫货订单无法申请售后');

        $ids = array_keys($request->array);
        $goodsList = ShopOrderGoodsLogic::getByWhere([
            'orderId' => $order->order_id,
            'whereIn' => ['id' => $ids],
        ]);
        if ($goodsList->count() !== count($ids)) return fail(422);
        $quantity = 0;
        foreach ($goodsList as $v) {
            $num = $request->array[$v->id];
            if ($v->quantity < $num) return fail(422);
            $quantity += $num;
        }

        if ($order->ext->status_deliver === 0) {
            $payPrice = $order->pay_price;
            $orRealPrice = $order->pay_price;
            $ensure = $order->order_ensure_price ?? 0;
        } else {
            $payPrice = bcsub($order->pay_price, $order->order_ensure_price, 2);
            $orRealPrice = $payPrice;
            $ensure = 0;
        }

        $model = ShopOrderReturnLogic::insertForModel([
            'buyUserId' => USERID,
            'sellUserId' => $order->sell_user_id,
            'orderId' => $order->order_id,
            'orType' => $request->type,
            'addUserId' => USERID,
            'editUserId' => USERID,
            'orReason' => $request->reason,
            'orNum' => $quantity,
            'orPrice' => $payPrice,
            'orRealPrice' => $orRealPrice,
            'orEnsurePrice' => $ensure,
            'orNote' => $request->remark ?? '',
            'imgIdJson' => $request->fileIds,
            'orAddTime' => time(),
            //'createdAt' => time(),
            'orderGoodsIds' => $request->array,
            'orContacts' => $order->order_contacts,
            'orContactsMobile' => $order->order_contacts_mobile,
            'orContactsAddress' => $order->order_contacts_address,
        ]);
        $order->ext->order_return_number = $model->serial_number;
        $order->ext->status_after_sale = 1;
        $order->ext->save();
        $goodsData = [
            'goods_order_no' => $order->serial_number,
            'order_return_no' => $model->serial_number,
            'goods_name' => $goodsList->toArray()[0]['title'],
            'time' => date('Y-m-d', time())
        ];
        WxMessageService::goodsWxMess($goodsData, [], [], 2);
        return success();
    }

    /**
     * addExpress
     * @param ProductOrderReturnAddExpressRequest $request
     * @return JsonResponse
     * @throws GuzzleException
     */
    public function addExpress(ProductOrderReturnAddExpressRequest $request): JsonResponse
    {
        $model = $this->logic->query()->where('serial_number', $request->serialNumber)
            ->whereIn('buy_user_id', array_unique([USERID, MAINID]))->first();
        if (is_null($model)) return failMessage("当前帐号下，售后订单号：$request->serialNumber,不存在");
        $model->or_sell_status = 4;
        $model->or_buy_status = 4;
        $model->save();
        LogisticsService::delivery($model->or_id, $request->expressNo, 1, 1);
        return success();
    }

    /**
     * audit
     * @param ProductOrderReturnAuditRequest $request
     * @return JsonResponse
     * @throws Exception
     */
    public function audit(ProductOrderReturnAuditRequest $request): JsonResponse
    {
        $model = $this->logic->query()->where('serial_number', $request->serialNumber)
            ->whereIn('sell_user_id', array_unique([USERID, MAINID]))->first();
        if (is_null($model)) return failMessage("当前帐号下，售后订单号：$request->serialNumber,不存在");

        if ((int)$request->status === 2) {
            if ((float)$request->price < 0) return fail(422);
            //发货不退保费，未发货退保费
            $price = $model->order->ext->status_deliver ? $model->or_price : $model->or_real_price;
            if ((float)$request->price > (float)$price) return failMessage('退款金额不能大于订单金额');
            if (!$request->refundType && $request->price <= 0) return failMessage('退款金额不能小于等于0');
            $model->or_real_price = $request->refundType ? $model->or_price : $request->price;
        }

        $model->or_approved_time = time();
        $model->or_sell_status = $request->status;
        $model->or_buy_status = $request->status;

        ShopOrderExtLogic::updateByWhere(['statusAfterSale' => $request->status,], 'orderId', $model->order_id);
        if ($request->status === 3) {//拒绝
            $model->or_sell_reject_remark = is_null($request->remark) ? '' : $request->remark;
            $model->save();
            return success();
        }

        ShopOrderLogic::updateByWhere(['orderBuyStatus' => 5, 'orderSellStatus' => 5], 'orderId', $model->order_id);
        if ($model->or_type === 2) {
            $model->or_sell_status = 5;
            $model->or_buy_status = 5;
            payLog(WechatService::refund($model)->toArray());
        }

        if ((int)$request->status === 2 && $model->or_type === 1) {
            $model->or_sell_status = 5;
            $model->or_buy_status = 5;
            payLog(WechatService::refund($model)->toArray());
        }
        $model->save();
        OperateLogLogic::add();
        return success();
    }

    /**
     * confirm
     * @param SerialNumberRequest $request
     * @return JsonResponse
     * @throws Exception
     */
    public function confirm(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->query()->where('serial_number', $request->serialNumber)
            ->whereIn('sell_user_id', array_unique([USERID, MAINID]))->first();
        if (is_null($model)) return failMessage("当前帐号下，售后订单号：$request->serialNumber,不存在");
        else if ($model->or_buy_status !== 4) return fail(422);
        $model->or_sell_status = 5;
        $model->or_buy_status = 5;
        $model->or_approved_time = time();
        $model->save();
        $model->order->order_sell_status = 5;
        $model->order->order_buy_status = 5;
        $model->order->save();
        payLog(WechatService::refund($model)->toArray());
        OperateLogLogic::add();
        return success();
    }

    private function hDetail(Model $model): void
    {
        if (is_null($model->order_goods_ids)) $model->good;
        else {
            $model->goods = ShopOrderGoodsLogic::getByWhere(['whereIn' => [
                'id', array_keys($model->order_goods_ids)]], null, [
                'id', 'price', 'title', 'spec', 'product_file_id', 'spec_file_id',
            ]);
        }
        if (!empty($model->img_id_json) && is_int($model->img_id_json[0])) {
            $model->img_id_json = ShopImageLogic::query()->whereIn('img_id', $model->img_id_json)->pluck('img_url')->toArray();
        }
    }

    public function delete(SerialNumberRequest $request)
    {
        $model = $this->logic->findBySerialNumber($request);
        if (is_null($model)) return fail(433);

        $model->or_is_delete = 1;
        $model->save();
        return success();
    }

    /**
     *
     * @param SerialNumberRequest $request
     * @return JsonResponse
     * @throws GuzzleException
     *
     */
    public function logistics(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->findByWhere(['serialNumber' => $request->serialNumber]);
        if (is_null($model)) return fail(433);
        else if (is_null($model->logistics)) return failMessage('买家暂未发货');
        else if ($model->oneLogistics->status_sign) return success($model->logistics);
        else return success(BaseLogisticsService::logistics($model));
    }

    public function sellerAddressList(): JsonResponse
    {
        return success(AddressLogic::getByWhere(['userId' => MAINID, 'isReturn' => 1]));
    }

    public function agreeRefundProduct(AgreeRefundProductRequest $request): JsonResponse
    {
        $model = $this->logic->findByWhere(['serialNumber' => $request->serialNumber]);
        if (is_null($model)) return fail(433);
        else if (!$model->order->ext->status_deliver) return fail(615);
        $address = AddressLogic::findByWhere(['id' => $request->addressId]);
        if (is_null($address)) return fail(433);
        $model->or_contacts = $address->contacts;
        $model->or_contacts_mobile = $address->mobile;
        $model->or_contacts_address = $address->full_address;
        $model->or_buy_status = 2;
        $model->or_sell_status = 2;
        $model->save();
        $model->order->ext->status_after_sale = 2;
        $model->order->ext->save();
        OperateLogLogic::add();
        return success();
    }

    public function cancelRefundProduct(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->findByWhere(['serialNumber' => $request->serialNumber]);
        if (is_null($model)) return fail(433);
        else if ($model->or_buy_status === 4) return fail(646);
        $model->or_contacts = null;
        $model->or_contacts_mobile = null;
        $model->or_contacts_address = null;
        $model->or_buy_status = 0;
        $model->or_sell_status = 0;
        $model->save();
        $model->order->ext->status_after_sale = 1;
        $model->order->ext->save();
        OperateLogLogic::add();
        return success();
    }

    public function cancel(SerialNumberRequest $request): JsonResponse
    {
        $model = $this->logic->findByWhere(['serialNumber' => $request->serialNumber]);
        if (is_null($model)) return fail(433);
        else if ($model->or_buy_status !== 1) return fail(646);

        $model->or_buy_status = 0;
        $model->or_sell_status = 0;
        $model->save();
        $model->order->ext->status_after_sale = 4;
        $model->order->ext->save();
        return success();
    }
}
